package Statistics;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.collections15.Transformer;

import Statistics.CompositeGraph.CompositeGraphNode;

import Config.Configure;

import edu.uci.ics.jung.graph.util.*;
import edu.uci.ics.jung.graph.DirectedSparseGraph;
import edu.uci.ics.jung.io.PajekNetWriter;

/**
 * @author Xenophon
 * This class will new a Graph instance of JUNG type from a given 
 * IDGraph instance, and store it in the Pajek format.
 */
public class IDGraphToJungGraph {
	/**
	 * @author Xenophon
	 * @version 2010-1-16
	 * This class is for the SCC View and Cluster View which need
	 * the parameter size.
	 */
	public static class MyNode
	{
		private String id;
		private int    size;
		public MyNode(String id,int size) 
		{
			this.id = id;
			this.size = size;
		}
		public String GetID(){return id;}
		public int    GetSize(){return size;}
		public String toString(){return id;}
		public boolean equals(Object o)
		{
			if (!(o instanceof MyNode))
				return false;
			return this.id.equals(((MyNode)o).GetID());
		}
		public int hashCode()
		{
			int res = 17;
			return 37*res+id.hashCode();
		}
	}
	public static class MyEdge{
		/*
		private int id;
		private int replyCnt;
		public MyEdge(int id,int replyCnt)
		{
			this.id = id;
			this.replyCnt = replyCnt;
		}
		public int GetID(){return id;}
		public int GetReplyCnt(){return replyCnt;}
		public String toString(){return "E"+id;}
		*/
		private int weight = 1;
		public  MyEdge(int weight){this.weight = weight;}
		public  int getWeight(){return weight;}
		public  String toString(){return "Weight:"+weight;}
	}
	public static DirectedSparseGraph<String, MyEdge> ToSparseGraph(IDGraph graph)
	{
		DirectedSparseGraph<String, MyEdge> sgraph = new DirectedSparseGraph<String, MyEdge>();
		HashMap<String, IDGraphNode> data = graph.GetNodeMap();
		for (Map.Entry<String, IDGraphNode> entry:data.entrySet()) {
			sgraph.addVertex(entry.getKey());
		}
		//int id = 0;
		for (Map.Entry<String, IDGraphNode> entry:data.entrySet()) {
			String source = entry.getKey();
			for (Map.Entry<String, Integer> nodeEntry: entry.getValue().GetOutEdges().entrySet()) {
				//sgraph.addEdge(new MyEdge(,nodeEntry.getValue()),source,nodeEntry.getKey(),EdgeType.DIRECTED);
				//id++;
				//sgraph.addEdge(new MyEdge(id, nodeEntry.getValue()),source,nodeEntry.getKey(),EdgeType.DIRECTED);
				sgraph.addEdge(new MyEdge(nodeEntry.getValue()),source,nodeEntry.getKey(),EdgeType.DIRECTED);
			}
		}
		return sgraph;
	}
	
	public static DirectedSparseGraph<String, MyEdge> CompositeGraphToSparseGraph(CompositeGraph graph)
	{
		DirectedSparseGraph<String, MyEdge> sgraph = new DirectedSparseGraph<String, MyEdge>();
		HashMap<String, CompositeGraphNode> data = graph.GetNodeMap();
		for (Map.Entry<String, CompositeGraphNode> entry:data.entrySet()) {
			sgraph.addVertex(entry.getKey());
		}
		//int id = 0;
		for (Map.Entry<String, CompositeGraphNode> entry:data.entrySet()) {
			String source = entry.getKey();
			for (Map.Entry<String, Integer> nodeEntry: entry.getValue().GetOutEdges().entrySet()) {
				sgraph.addEdge(new MyEdge(nodeEntry.getValue()),source,nodeEntry.getKey(),EdgeType.DIRECTED);
			}
		}
		return sgraph;
	}
	public static DirectedSparseGraph<MyNode, MyEdge> NewCompositeGraphToSparseGraph(CompositeGraph graph)
	{
		DirectedSparseGraph<MyNode, MyEdge> sgraph = new DirectedSparseGraph<MyNode, MyEdge>();
		HashMap<String, CompositeGraphNode> data = graph.GetNodeMap();
		for (Map.Entry<String, CompositeGraphNode> entry:data.entrySet()) {
			MyNode node = new MyNode(entry.getKey(), entry.getValue().GetSize());
			sgraph.addVertex(node);
		}
		//int id = 0;
		for (Map.Entry<String, CompositeGraphNode> entry:data.entrySet()) {
			MyNode source = new MyNode(entry.getKey(), entry.getValue().GetSize());
			for (Map.Entry<String, Integer> nodeEntry: entry.getValue().GetOutEdges().entrySet()) {
				MyNode target = new MyNode(nodeEntry.getKey(), entry.getValue().GetSize());
				sgraph.addEdge(new MyEdge(nodeEntry.getValue()),source,target,EdgeType.DIRECTED);
			}
		}
		return sgraph;
	}
	
	public static void StoreIDGraphInPajekFormat(IDGraph graph)
	{
		Transformer<String, String> nodeTransformer = new Transformer<String, String>() {
			public String transform(String id){return id;}
		};
		Transformer<MyEdge,Number> edgeTransformer = new Transformer<MyEdge, Number>(){
			public Number transform(MyEdge edge){return edge.getWeight();}
		};
		PajekNetWriter<String, MyEdge> pWriter = new PajekNetWriter<String, MyEdge>();
		try {
			pWriter.save(ToSparseGraph(graph),Configure.PAJEK_DIR,nodeTransformer,edgeTransformer);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
